package com.xxxx.server.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.server.mapper.AdminRoleMapper;
import com.xxxx.server.mapper.MenuMapper;
import com.xxxx.server.mapper.MenuRoleMapper;
import com.xxxx.server.pojo.Admin;
import com.xxxx.server.pojo.Menu;
import com.xxxx.server.pojo.RespBean;
import com.xxxx.server.service.IMenuService;
import com.xxxx.server.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhoubin
 * @since 2020-10-15
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

	@Resource
	private MenuMapper menuMapper;
	@Resource
	private RedisTemplate redisTemplate;
	@Resource
	private MenuRoleMapper menuRoleMapper;
	@Resource
	private AdminRoleMapper adminRoleMapper;
	/**
	 * 通过用户id获取菜单列表
	 *
	 * @return
	 */
	@Override
	public List<Menu> getMenusByAdminId() {
		//获取Id
		Integer adminId = ((Admin)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId();
		//从redis中获取菜单缓存数据
		ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
		//查询缓存中是否有数据
		List<Menu> menus = (List<Menu>) valueOperations.get("menu_" + adminId);
		//如果没数据，数据库中查询，并设置到缓存中
		if (CollectionUtils.isEmpty(menus)){
			menus = menuMapper.getMenusByAdminId(adminId);
			valueOperations.set("menu_"+adminId,menus);
		}
		return menus;

	}


	/**
	 * 查询所有菜单及对应角色
	 *
	 * @return
	 */
	@Override
	public List<Menu> getMenusWithRoles() {
		return menuMapper.getMenusWithRoles();
	}

	/**
	 * 根据角色id查询菜单
	 * @param rid
	 * @return 角色对应的菜单集合
	 */
	@Override
	public List<Menu> getMenusByRoleId(Integer rid) {
		AssertUtil.isTrue(null==rid,"角色id不能为空");
		//获得一级菜单
		List<Menu> menus = menuMapper.selectMenusByRoleId(rid,1);
		AssertUtil.isTrue(null==menus || menus.size()<1,"该角色暂无权限");
		//遍历一级菜单
		menus.forEach(t->{
			//查询一级菜单下的子菜单
			List<Menu> children = menuMapper.selectMenusByRoleId(rid, t.getId());
			t.setChildren(children);
		});
		System.out.println(menus);
		//返回菜单
		return menus;
	}

	/**
	 * 查询所有菜单
	 *
	 * @return 菜单列表
	 */
	@Override
	public List<Menu> getMenusAll() {
		//获取根目录	(所有)
		List<Menu> allMenus = menuMapper.getRootMenu();
		//查询所有parentId为1的菜单
		List<Menu> menus = menuMapper.getMenusByParentId(allMenus.get(0).getId());
		//遍历一级菜单，查询其对应的二级菜单
		menus.forEach(t->{
			//查询当前菜单的所有子菜单
			List<Menu> children =menuMapper.getMenusByParentId(t.getId());
			t.setChildren(children);
		});
		//应为根节点只有一条数据，因此可以直接这样赋值
		allMenus.get(0).setChildren(menus);
		return allMenus;
	}

	/**
	 * 根据角色id查询所有权限id
	 *
	 * @param rid
	 * @return
	 */
	@Override
	public List<Integer> getMidsByRid(Integer rid) {
		return menuRoleMapper.selectMenusIdsByRoleId(rid);
	}

	/**
	 * 修改角色访问资源
	 * @param rid
	 * @param mids
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public RespBean updateMenuRole(Integer rid, Integer[] mids) {
		AssertUtil.isTrue(null==rid,"角色id不能为空");
		AssertUtil.isTrue(null==menuMapper.selectById(rid),"该角色不存在");
		Integer addCount=0;
		//查询该角色对应的所有权限
		Integer count = menuRoleMapper.getCountByRoleId(rid);
		//根据角色id删除，返回删除条数
		Integer  delMenus = menuRoleMapper.deleteByRoleId(rid);
		AssertUtil.isTrue(delMenus!=count,"修改失败");
		//判断菜单id
		if (null==mids||mids.length==0){
			return RespBean.success("修改成功");
		}else {

			 addCount = menuRoleMapper.insertMenuRole(rid, mids);
		}
		AssertUtil.isTrue(addCount!=mids.length,"修改失败");

		//获取拥有该角色的adminId集合
		List<Integer> adminIdList = adminRoleMapper.selectAdminIdsByRoleId(rid);
		//清空redis中的缓存
		adminIdList.forEach(t->{
			redisTemplate.delete("menu_"+t);
		});

		return RespBean.success("修改成功,权限会在相关操作员重新登录后刷新");
	}
}
